iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0

昨天延伸了類別講到了物件與單例,熟悉 Java 的讀者這時候可能會想到,在 Java 裡面還有一個靜態變數呼現在都還有提到。沒錯,在 Java 內我們常會用 static 字樣在同一種類別之間做出一個具有單例特性的變數,但確實在 Kotlin 這項設計並沒有直接被 Kotlin 採用。

那麼問題來了,要怎麼去滿足只共享於相同類別的單例的需求呢?Kotlin 提供了 companion object (伴生物件) 這樣的方法。

在 Kotlin 裡,伴生物件宣告在類別內部,用於定義與類別本身相關而不是類別實例相關的靜態變數或函式。

class Person(val name: String, val age: Int) {
    companion object {
        const val species = "Homo sapiens"

        fun createDefaultPerson(): Person {
            return Person("Unknown", 0)
        }
    }

    fun greet() {
        println("你好,我叫 $name,我 $age 歲。")
    }
}

在上述範例中,我們在 Person 類別裡加入了一個伴生物件。這個伴生物件有一個常數變數 species 和一個函式 createDefaultPerson(),該函式會返回有預設傳入參數的 Person 物件。如果我們想要一個類別裡的存取伴生物件,可以使用類別名稱後跟 companion object 內容的變數或函示名稱:

val defaultPerson = Person.createDefaultPerson()
println("預設人物:${defaultPerson.name},${defaultPerson.age}") // 預設人物:Unknown,0
println("物種:${Person.species}")                              // 物種:Homo sapiens

這裡我們可以發現,跟在 Java 使用靜態變數相似,我們可以不用真的從 Person 這個類別去建立一個新物件才可以使用伴生物件的內容;反之,我們可以直接使用 Person 類別內的伴生物件,而上述案例則會在伴生物件內直接生成一個 Person 物件。

讓我們再用一個範例看另一個伴生物件的功用:

class Person{
    private val heightCm = 170
    
    companion object {
        fun getHeightCm(instance: Person): Int {
            return instance.heightCm 
        }
    }
}

val john = Person()
val johnHeight = Person.getHeightCm(john)  // 成功獲得 170
println(johnHeight) // 170

從上面的範例中,若我們將伴生物件換成單例,我們將無法存取 Person 這個伴生物件的類別中的私有變數,這也是會需要使用到伴生物件的場景之一。


上一篇
Day 17 Kotlin 物件
下一篇
Day 19 Kotlin 繼承
系列文
成為一名 Kotlin 後端攻城獅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言